package com.feidee.bigdata.bloomfilterserv.dao.impl;

import com.alibaba.fastjson.JSON;
import com.feidee.bigdata.bloomfilterserv.constant.Constant;
import com.feidee.bigdata.bloomfilterserv.dao.IBloomFilterDao;
import com.feidee.bigdata.bloomfilterserv.model.QueryBfKeysModel;
import com.feidee.bigdata.bloomfilterserv.model.RequestParamModel;
import com.google.common.base.Charsets;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class BloomFilterDaoImpl implements IBloomFilterDao {

	private Logger logger = LoggerFactory.getLogger(BloomFilterDaoImpl.class);
	public static BloomFilter<CharSequence> bloomFilter;

	public BloomFilterDaoImpl() {

		bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), Constant.BF_EXCEPTED_INSERTIONS, Constant.BF_FPP);
		logger.info("===布隆过滤器初始化: BF_EXCEPTED_INSERTIONS:" + Constant.BF_EXCEPTED_INSERTIONS +
				",BF_FPP:" + Constant.BF_FPP);

	}

	/**
	 * 判断一批元素是否已在布隆过滤器中
	 *
	 * @param rpm
	 * @return
	 */
	@Override
	public Map<String, Boolean> judgeMetaIsInBF(RequestParamModel rpm) {

		Map<String, Boolean> blCalcRes = new HashMap<>();

		List<QueryBfKeysModel> queryBfKeyModelList = rpm.getQueryKeyMap();
		for (QueryBfKeysModel queryBfKeysModel : queryBfKeyModelList) {
			List<String> queryKeyList = queryBfKeysModel.getQueryKeyList();
			boolean containRes = Boolean.FALSE;
			if (mightContainInBF(queryBfKeysModel.getWriteToBfKey())) {
				containRes = Boolean.TRUE;
			}

			for (String queryKey : queryKeyList) {
				if (mightContainInBF(queryKey)) {
					containRes = Boolean.TRUE;
				}
			}

			if (!containRes) {
				addMetaToBF(queryBfKeysModel.getWriteToBfKey());
			}
			blCalcRes.put(queryBfKeysModel.getWriteToBfKey(), containRes);
		}

		return blCalcRes;
	}

	/**
	 * 判断指定元素是否已在布隆过滤器中
	 *
	 * @param meta
	 * @return
	 */
	private boolean mightContainInBF(String meta) {

		return bloomFilter.mightContain(meta);

	}

	/**
	 * 添加一个新元素
	 *
	 * @param meta
	 */
	public void addMetaToBF(String meta) {

		bloomFilter.put(meta);

	}

	/**
	 * 初始化一个新的布隆过滤器
	 *
	 * @param meta
	 */
	@Override
	public void clearBF() {

		bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), Constant.BF_EXCEPTED_INSERTIONS, Constant.BF_FPP);

	}

	public static void main(String[] args) {

		RequestParamModel requestParamModel = new RequestParamModel();
		requestParamModel.setIpPrefix("146");

		List<QueryBfKeysModel> queryBfKeysModelList = new ArrayList<>();
		QueryBfKeysModel queryBfKeysModel = new QueryBfKeysModel();
		List<String> queryKeyList = new ArrayList<>();
		queryKeyList.add("a1");
		queryKeyList.add("a2");
		queryKeyList.add("a3");
		queryKeyList.add("a4");
		queryBfKeysModel.setQueryKeyList(queryKeyList);
		queryBfKeysModel.setWriteToBfKey("a1");

		QueryBfKeysModel queryBfKeysModel1 = new QueryBfKeysModel();
		List<String> queryKeyList1 = new ArrayList<>();
		queryKeyList1.add("a1");
		queryKeyList1.add("a2");
		queryKeyList1.add("a3");
		queryKeyList1.add("a4");
		queryBfKeysModel1.setQueryKeyList(queryKeyList1);
		queryBfKeysModel1.setWriteToBfKey("a2");

		QueryBfKeysModel queryBfKeysModel2 = new QueryBfKeysModel();
		List<String> queryKeyList2 = new ArrayList<>();
		queryKeyList2.add("a1");
		queryKeyList2.add("a2");
		queryKeyList2.add("a3");
		queryKeyList2.add("a4");
		queryBfKeysModel2.setQueryKeyList(queryKeyList2);
		queryBfKeysModel2.setWriteToBfKey("a3");

		QueryBfKeysModel queryBfKeysModel3 = new QueryBfKeysModel();
		List<String> queryKeyList3 = new ArrayList<>();
		queryKeyList3.add("a1");
		queryKeyList3.add("a2");
		queryKeyList3.add("a3");
		queryKeyList3.add("a4");
		queryBfKeysModel3.setQueryKeyList(queryKeyList3);
		queryBfKeysModel3.setWriteToBfKey("a4");

		QueryBfKeysModel queryBfKeysModel4 = new QueryBfKeysModel();
		List<String> queryKeyList4 = new ArrayList<>();
		queryKeyList4.add("a5");
		queryKeyList4.add("a6");
		queryKeyList4.add("a7");
		queryKeyList4.add("a8");
		queryBfKeysModel4.setQueryKeyList(queryKeyList4);
		queryBfKeysModel4.setWriteToBfKey("a6");

		QueryBfKeysModel queryBfKeysModel5 = new QueryBfKeysModel();
		List<String> queryKeyList5 = new ArrayList<>();
		queryKeyList5.add("a9");
		queryKeyList5.add("a10");
		queryKeyList5.add("a11");
		queryKeyList5.add("a12");
		queryBfKeysModel5.setQueryKeyList(queryKeyList5);
		queryBfKeysModel5.setWriteToBfKey("a9");

		queryBfKeysModelList.add(queryBfKeysModel);
		queryBfKeysModelList.add(queryBfKeysModel1);
		queryBfKeysModelList.add(queryBfKeysModel2);
		queryBfKeysModelList.add(queryBfKeysModel3);
		queryBfKeysModelList.add(queryBfKeysModel4);
		queryBfKeysModelList.add(queryBfKeysModel5);
		requestParamModel.setQueryKeyMap(queryBfKeysModelList);
		System.out.println(JSON.toJSONString(requestParamModel));
		System.out.println(JSON.toJSONString(new BloomFilterDaoImpl().judgeMetaIsInBF(requestParamModel)));

	}

}
